package com.sgzn.sgpay.service.tcp;

import com.sgzn.sgpay.container.ServicePrivinder;
import com.sgzn.sgpay.enums.AppName;
import com.sgzn.sgpay.enums.TcpReceiveEnum;
import com.sgzn.sgpay.service.tcp.api.TcpLoginService;
import com.sgzn.sgpay.service.tcp.api.TcpRefundService;
import com.sgzn.sgpay.service.tcp.impl.TcpHeartBeatServiceImpl;
import com.sgzn.sgpay.service.tcp.impl.TcpLoginServiceImpl;
import com.sgzn.sgpay.service.tcp.impl.TcpRefundServiceImpl;
import com.sgzn.sgpay.service.tcp.receive.TcpReceiveCallHandler;
import com.sgzn.sgpay.service.tcp.receive.modle.TcpReceiveCallRequest;
import com.sgzn.sgpay.util.SerialNoUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.Date;

/**
 * Created by xxjs-gd-llf
 * DATETIME:2018/4/22 10:54
 * Description:
 */
@Slf4j
public class SgsTcpListenService extends Thread{

    private int LENGTH = 7;

    private Socket socket;



    public SgsTcpListenService(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run(){
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String temp;
            while ((temp=br.readLine()) != null) {
                String initiationID = SerialNoUtil.generateSerialNo(AppName.SGT);
                org.slf4j.MDC.put("initiationID", initiationID);
                log.info("监听收到终端请求{}",temp);
                parseProtocol(temp.trim(), initiationID);
            }
        }catch ( IOException e ){
            e.printStackTrace();
        }
    }

    /**
     * 根据CMD派到相应的Service处理
     * @param strRecv
     * @param initiationID
     */
    private void parseProtocol(String strRecv, String initiationID){
        log.info("==============start parseProtocol==============",strRecv);
        //判断协议超始是否OK
        if( !strRecv.startsWith(SgTcpProtocolHead.TCP_PROTOCOL_HEAD) || !strRecv.endsWith(SgTcpProtocolHead.TCP_PROTOCOL_END) ){
            log.info("报文格式不对:{}",strRecv);
            return;
        }
        String[] recvArray = strRecv.split(SgTcpProtocolHead.TCP_PROTOCOL_SEPERATOR);
        String strCmd =  recvArray[1];

        if( SgTcpProtocolHead.TCP_LOGIN_REQUEST.equals(strCmd)){

            log.info("收到登录请求{}",strRecv);
            TcpLoginService tcpLoginService = new TcpLoginServiceImpl();
            tcpLoginService.tcpAnswerLogin(strRecv,socket);

        }else if( SgTcpProtocolHead.TCP_LOGIN_CHECK_REQUEST.equals(strCmd) ){

            log.info("收到登录认证请求{}",strRecv);
            TcpLoginService tcpLoginService = new TcpLoginServiceImpl();
            tcpLoginService.tcpAnswerCheckLogin(strRecv,socket);

        }
        else if(SgTcpProtocolHead.TCP_HEARTBEAT_REQUEST.equals(strCmd)){
            log.info("收到心跳请求报文:{}",strRecv);
            TcpHeartBeatServiceImpl tcpHeartBeatService = new TcpHeartBeatServiceImpl();
            tcpHeartBeatService.tcpAnswerHeartBeat(strRecv,socket);

        }else if(SgTcpProtocolHead.TCP_REFUND_REQUEST.equals(strCmd)){
            log.info("收到退款请求:{}",strRecv);
            TcpRefundService tcpRefundService = new TcpRefundServiceImpl();
            tcpRefundService.tcpAnswerRefund(strRecv,socket);

        }else if(SgTcpProtocolHead.TCP_SERIAL_ACK.equals(strCmd)){
            log.info("start:{}", strCmd);
            if (recvArray.length != this.LENGTH) {
                log.info("the format protocol is  wrong.{},{}",recvArray.length, this.LENGTH);
                return;
            }
            //校验和检查
            if( ! recvArray[5].equals(SgTcpProtocolHead.DEFAULT_PROTOCOL_CHECKSUM) ){
                log.info("checksum is wrong.{},{}",recvArray[5],SgTcpProtocolHead.DEFAULT_PROTOCOL_CHECKSUM);
                return;
            }

            //根据解析协议
            String protocolContext = recvArray[4];
            log.info("protocolContext:{}", protocolContext);
            if (StringUtils.isNotBlank(protocolContext)) {
                String cmd = protocolContext.substring(6, 8); log.info("cmd:{}", cmd);
                TcpReceiveEnum explain = TcpReceiveEnum.explain(cmd);
                log.info("收到终端[{}]请求：{}", explain.getCmdName(), strRecv);
                try {
                    TcpReceiveCallHandler handler = (TcpReceiveCallHandler) ServicePrivinder.getBean(explain.getBeanName());
                    TcpReceiveCallRequest receRequest = assembleReceiveRequest(strRecv, initiationID, recvArray, protocolContext, explain);
                    log.info("send request PARAM:{}",receRequest.toString());
                    handler.handle(receRequest);
                } catch (Exception e) {
                    log.warn("获取服务出错：{}", e.getMessage());
                }
            }

        }
        else {
            log.info("不匹配的报文协议:{}",strRecv);
        }
        log.info("=================end parseProtocol=================");
    }


    /**
     * 组装请求
     * @param strRecv
     * @param initiationID
     * @param recvArray
     * @param protocolContext
     * @param explain
     * @return
     */
    private TcpReceiveCallRequest assembleReceiveRequest(String strRecv, String initiationID, String[] recvArray, String protocolContext, TcpReceiveEnum explain) {
        TcpReceiveCallRequest receRequest = new TcpReceiveCallRequest();
        receRequest.setSocket(socket);
        receRequest.setReceiveContent(strRecv);
        receRequest.setRecvArray(recvArray);
        receRequest.setCmdName(explain.getCmdName());
        receRequest.setDeviceId(recvArray[2]);
        receRequest.setReqSeq(recvArray[3]);
        receRequest.setProtocolContext(recvArray[4]);
        receRequest.setLength(protocolContext.substring(2,4));
        receRequest.setIndex(protocolContext.substring(4,6));
        receRequest.setCmd(explain.getCmd());
        receRequest.setInitiationID(initiationID);
        receRequest.setReqTime(new Date());
        receRequest.setLoginChannel(AppName.SGT.getCode());
        return receRequest;
    }
}
